package restful

import (
	"log"
	"moss/status"
	"net/http"
	"net/http/httputil"
	"strings"
	"strconv"
	"moss/conf"
	"github.com/gorilla/mux"
)

func ComplexRequestHandler(w http.ResponseWriter, req *http.Request) {
	requestId := generateRequestId()
	// Special treatment for invalid bucket name
	// If bucket name included %2F (/), the muxer may redirect here
	if strings.Count(req.URL.Path, "/") > 1 {
		reportError(w, req, status.InvalidBucketName, requestId)
		return
	}

	b, _ := httputil.DumpRequest(req, false)
	log.Println(string(b))
	reportError(w, req, status.MethodNotAllowed, requestId)
}

func StartHttpServer(port uint16) {
	ServiceHostPattern := conf.Config.Name.ServiceHostPattern
	BucketHostPattern := strings.Replace(conf.Config.Name.BucketHostPattern, "BUCKET", "{bucket}", 1)
	ObjectPathPattern := strings.Replace(conf.Config.Name.ObjectPathPattern, "OBJECT", "{object:.+}", 1)

	// Bind method and path to related handlerFunc
	r := mux.NewRouter()

	r.Methods("PUT").Path(ObjectPathPattern).
		Host(BucketHostPattern).
		Queries("symlink", "").
		Headers(conf.HTTPHeaderOssSymlinkTarget, "").
		HandlerFunc(PutSymlinkHandler)

	r.Methods("PUT").Path(ObjectPathPattern).
		Host(BucketHostPattern).
		Queries("partNumber", "{partNumber}", "uploadId", "{uploadId}").
		Headers(conf.HTTPHeaderOssCopySource, "", conf.HTTPHeaderOssCopySourceRange, "").
		HandlerFunc(UploadPartCopyHandler)

	r.Methods("PUT").Path(ObjectPathPattern).
		Host(BucketHostPattern).
		Queries("partNumber", "{partNumber}", "uploadId", "{uploadId}").
		HandlerFunc(UploadPartHandler)

	r.Methods("PUT").Path(ObjectPathPattern).
		Host(BucketHostPattern).
		Queries("acl", "").
		HandlerFunc(PutObjectAclHandler)

	r.Methods("PUT").Path(ObjectPathPattern).
		Host(BucketHostPattern).
		Headers(conf.HTTPHeaderOssCopySource, "").
		HandlerFunc(CopyObjectHandler)

	r.Methods("PUT").Path(ObjectPathPattern).
		Host(BucketHostPattern).
		HandlerFunc(PutObjectHandler)

	r.Methods("PUT").Path("/").
		Host(BucketHostPattern).
		Queries("acl", "").
		HandlerFunc(PutBucketAclHandler)

	r.Methods("PUT").Path("/").
		Host(BucketHostPattern).
		Queries("logging", "").
		HandlerFunc(PutBucketLoggingHandler)

	r.Methods("PUT").Path("/").
		Host(BucketHostPattern).
		Queries("website", "").
		HandlerFunc(PutBucketWebsiteHandler)

	r.Methods("PUT").Path("/").
		Host(BucketHostPattern).
		Queries("referer", "").
		HandlerFunc(PutBucketRefererHandler)

	r.Methods("PUT").Path("/").
		Host(BucketHostPattern).
		Queries("lifecycle", "").
		HandlerFunc(PutBucketLifecycleHandler)

	r.Methods("PUT").Path("/").
		Host(BucketHostPattern).
		HandlerFunc(PutBucketHandler)

	r.Methods("GET").Path(ObjectPathPattern).
		Host(BucketHostPattern).
		Queries("objectMeta", "").
		HandlerFunc(GetObjectMetaHandler)

	r.Methods("GET").Path(ObjectPathPattern).
		Host(BucketHostPattern).
		Queries("acl", "").
		HandlerFunc(GetObjectAclHandler)

	r.Methods("GET").Path(ObjectPathPattern).
		Host(BucketHostPattern).
		Queries("symlink", "").
		HandlerFunc(GetSymlinkHandler)

	r.Methods("GET").Path(ObjectPathPattern).
		Host(BucketHostPattern).
		Queries("uploadId", "{uploadId}").
		HandlerFunc(ListPartsHandler)

	r.Methods("GET").Path(ObjectPathPattern).
		Host(BucketHostPattern).
		HandlerFunc(GetObjectHandler)

	r.Methods("GET").Path("/").
		Host(BucketHostPattern).
		Queries("uploads", "").
		HandlerFunc(ListMultipartUploadsHandler)

	r.Methods("GET").Path("/").
		Host(BucketHostPattern).
		Queries("acl", "").
		HandlerFunc(GetBucketAclHandler)

	r.Methods("GET").Path("/").
		Host(BucketHostPattern).
		Queries("location", "").
		HandlerFunc(GetBucketLocationHandler)

	r.Methods("GET").Path("/").
		Host(BucketHostPattern).
		Queries("logging", "").
		HandlerFunc(GetBucketLoggingHandler)

	r.Methods("GET").Path("/").
		Host(BucketHostPattern).
		Queries("website", "").
		HandlerFunc(GetBucketWebsiteHandler)

	r.Methods("GET").Path("/").
		Host(BucketHostPattern).
		Queries("referer", "").
		HandlerFunc(GetBucketRefererHandler)

	r.Methods("GET").Path("/").
		Host(BucketHostPattern).
		Queries("lifecycle", "").
		HandlerFunc(GetBucketLifecycleHandler)

	r.Methods("GET").Path("/").
		Host(BucketHostPattern).
		Queries("bucketInfo", "").
		HandlerFunc(GetBucketInfoHandler)

	r.Methods("GET").Path("/").
		Host(BucketHostPattern).
		HandlerFunc(GetBucketHandler)

	r.Methods("GET").Path("/").
		Host(ServiceHostPattern).
		HandlerFunc(GetServiceHandler)

	r.Methods("POST").Path(ObjectPathPattern).
		Host(BucketHostPattern).
		Queries("append", "", "position", "{position}").
		HandlerFunc(AppendObjectHandler)

	r.Methods("POST").Path(ObjectPathPattern).
		Host(BucketHostPattern).
		Queries("uploads", "").
		HandlerFunc(InitiateMultipartUploadHandler)

	r.Methods("POST").Path(ObjectPathPattern).
		Host(BucketHostPattern).
		Queries("uploadId", "{uploadId}").
		HandlerFunc(CompleteMultipartUploadHandler)

	r.Methods("POST").Path("/").
		Host(BucketHostPattern).
		Queries("delete", "").
		HandlerFunc(DeleteMultipleObjectsHandler)

	r.Methods("POST").Path("/").
		Host(BucketHostPattern).
		HandlerFunc(PostObjectHandler)

	r.Methods("DELETE").Path(ObjectPathPattern).
		Host(BucketHostPattern).
		Queries("uploadId", "").
		HandlerFunc(AbortMultipartUploadHandler)

	r.Methods("DELETE").Path(ObjectPathPattern).
		Host(BucketHostPattern).
		HandlerFunc(DeleteObjectHandler)

	r.Methods("DELETE").Path("/").
		Host(BucketHostPattern).
		Queries("logging", "").
		HandlerFunc(DeleteBucketLoggingHandler)

	r.Methods("DELETE").Path("/").
		Host(BucketHostPattern).
		Queries("website", "").
		HandlerFunc(DeleteBucketWebsiteHandler)

	r.Methods("DELETE").Path("/").
		Host(BucketHostPattern).
		Queries("lifecycle", "").
		HandlerFunc(DeleteBucketLifecycleHandler)

	r.Methods("DELETE").Path("/").
		Host(BucketHostPattern).
		HandlerFunc(DeleteBucketHandler)

	r.Methods("HEAD").Path(ObjectPathPattern).
		Host(BucketHostPattern).
		HandlerFunc(HeadObjectHandler)

	r.Path("/").HandlerFunc(ComplexRequestHandler)

	http.Handle("/", r)
	err := http.ListenAndServe(":"+strconv.Itoa(int(port)), nil)
	if err != nil {
		log.Println(err)
	}
}
